package com.gframework.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;

import org.springframework.lang.Nullable;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

/**
 * json、jackson操作工具类.
 * <p>
 * jackson的ObjectMapper是线程安全，可复用的。因此每次使用前都进行初始化
 * 重复设置参数会非常的麻烦，此工具类的ObjectMapper采用的是默认策略为：
 * <ul>
 * <li>忽略不存在的属性</li>
 * <li>空对象不抛出异常</li>
 * </ul>，
 * 保证正反序列化不会出现异常的一个ObjectMapper对象进行操作。
 * <p>
 * 如果你需要更多高级的设置，那么你可以使用自定义的ObjectMapper对象。
 * <p>
 * 同时需要注意的是，jackson的操作中，readTree的性能远远超过readValue，经过简单测定发现快至少10倍以上。
 * 
 * @since 1.0.0
 * @author Ghwolf
 *         XXX 目前仅仅只是因为避免过多的手动实例化ObjectMapper而产生的此类，但是此类功能还并不够强大。并不能够算是好用的工具类。
 */
public class JsonUtils {

	private JsonUtils() {
	}

	private static final ObjectMapper MAPPER = new ObjectMapper();

	static {
		MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		MAPPER.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
	}
	
	/**
	 * 获取ObjectMapper原始对象
	 */
	public static ObjectMapper get() {
		return MAPPER;
	}
	
	/**
	 * 判断一个字符串是否是json格式的
	 * @param str 要判断的字符串
	 * @return 如果是，则返回true，否则返回false，如果参数为null，返回false
	 */
	public static boolean isJson(@Nullable String str) {
		if (str == null) return false ;
		try {
			MAPPER.readTree(str);
			return true ;
		} catch(Exception e) {
			return false ;
		}
	}
	

	public static JsonNode readTree(String json) throws IOException {
		return MAPPER.readTree(json);
	}

	public static JsonNode readTree(byte[] data) throws IOException {
		return MAPPER.readTree(data);
	}

	public static JsonNode readTree(InputStream inputStream) throws IOException {
		return MAPPER.readTree(inputStream);
	}

	public static JsonNode readTree(File file) throws IOException {
		return MAPPER.readTree(file);
	}

	public static JsonNode readTree(Reader reader) throws IOException {
		return MAPPER.readTree(reader);
	}

	public static <T> T readValue(String str, Class<T> type)
			throws JsonParseException, JsonMappingException, IOException {
		return MAPPER.readValue(str, type);
	}

	public static <T> T readValue(byte[] data, Class<T> type)
			throws JsonParseException, JsonMappingException, IOException {
		return MAPPER.readValue(data, type);
	}
	
	public static <T> T readValue(String str, Object obj)
			throws JsonParseException, JsonMappingException, IOException {
		return MAPPER.readerForUpdating(obj).readValue(str);
	}
	
	public static <T> T readValue(byte[] data, Object obj)
			throws JsonParseException, JsonMappingException, IOException {
		return MAPPER.readerForUpdating(obj).readValue(data);
	}

	public static String writeValue(Object value) throws JsonProcessingException {
		return MAPPER.writeValueAsString(value);
	}
	
	public static byte[] writeBytes(Object value) throws JsonProcessingException {
		return MAPPER.writeValueAsBytes(value);
	}
	
	public static void writeToFile(File file,Object value) throws IOException {
		MAPPER.writeValue(file, value);
	}
	
	public static void writeValue(Writer writer,Object value) throws IOException {
		MAPPER.writeValue(writer, value);
	}
	
	public static void writeValue(OutputStream output,Object value) throws IOException {
		MAPPER.writeValue(output, value);
	}

	/**
	 * 格式化输出json并返回，如果转换出错则返回null
	 */
	public static String writeValueFormatter(Object value){
		try {
			return MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(value);
		} catch (JsonProcessingException e) {
			return null;
		}
	}
	
	/**
	 * 如果转换出现异常，则返回null
	 */
	public static JsonNode readTreeOrNull(String json) {
		try {
			return readTree(json);
		} catch (IOException e) {
			return null ;
		}
	}
	/**
	 * 如果转换出现异常，则返回null
	 */
	public static JsonNode readTreeOrNull(byte[] data) {
		try {
			return readTree(data);
		} catch (IOException e) {
			return null ;
		}
	}
	/**
	 * 如果转换出现异常，则返回null
	 */
	public static JsonNode readTreeOrNull(InputStream inputStream) {
		try {
			return readTree(inputStream);
		} catch (IOException e) {
			return null ;
		}
	}
	/**
	 * 如果转换出现异常，则返回null
	 */
	public static JsonNode readTreeOrNull(File file) {
		try {
			return readTree(file);
		} catch (IOException e) {
			return null ;
		}
	}
	/**
	 * 如果转换出现异常，则返回null
	 */
	public static JsonNode readTreeOrNull(Reader reader) {
		try {
			return readTree(reader);
		} catch (IOException e) {
			return null ;
		}
	}
	/**
	 * 如果转换出现异常，则返回null
	 */
	public static <T> T readValueOrNull(String str, Class<T> type) {
		try {
			return readValue(str, type);
		} catch (IOException e) {
			return null ;
		}
	}
	/**
	 * 如果转换出现异常，则返回null
	 */
	public static <T> T readValueOrNull(byte[] data, Class<T> type) {
		try {
			return readValue(data, type);
		} catch (IOException e) {
			return null ;
		}
	}
	/**
	 * 如果转换出现异常，则返回null
	 */
	public static <T> T readValueOrNull(String str, Object obj) {
		try {
			return readValue(str, obj);
		} catch (IOException e) {
			return null ;
		}
	}
	/**
	 * 如果转换出现异常，则返回null
	 */
	public static <T> T readValueOrNull(byte[] data, Object obj) {
		try {
			return readValue(data, obj);
		} catch (IOException e) {
			return null ;
		}
	}
	/**
	 * 如果转换出现异常，则返回null
	 */
	public static String writeValueOrNull(Object value) {
		try {
			return writeValue(value);
		} catch (JsonProcessingException e) {
			return null ;
		}
	}
	/**
	 * 如果转换出现异常，则返回""
	 */
	public static String writeValueOrEmpty(Object value) {
		try {
			return writeValue(value);
		} catch (JsonProcessingException e) {
			return "" ;
		}
	}
	/**
	 * 如果转换出现异常，则返回null
	 */
	public static byte[] writeBytesOrNull(Object value) {
		try {
			return writeBytes(value);
		} catch (JsonProcessingException e) {
			return null;
		}
	}
	/**
	 * 如果转换出现异常，则返回 new byte[0]
	 */
	public static byte[] writeBytesOrEmpty(Object value) {
		try {
			return writeBytes(value);
		} catch (JsonProcessingException e) {
			return new byte[0] ;
		}
	}
	
	
}
